#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
NSA5312 UART测试工具 - PyQt5版本
支持9位数据发送（利用奇偶校验位）和8位数据接收
"""

import sys
import time
import datetime
import queue
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import serial
import serial.tools.list_ports

class SerialWorker(QThread):
    """串口工作线程 - 状态机模式"""
    data_received = pyqtSignal(bytes, str)  # 接收到的数据和时间戳
    connection_changed = pyqtSignal(bool)   # 连接状态变化
    error_occurred = pyqtSignal(str)        # 错误信息

    # 串口模式枚举
    MODE_RECEIVE = 0      # 接收模式：8位数据，无校验位
    MODE_SEND_ADDR = 1    # 地址发送模式：9位数据，MARK校验
    MODE_SEND_DATA = 2    # 数据发送模式：9位数据，SPACE校验

    def __init__(self):
        super().__init__()
        self.serial_port = None
        self.running = False
        self.send_queue = queue.Queue()
        self.current_mode = self.MODE_RECEIVE  # 默认接收模式
        self.port_name = ""
        self.baudrate = 9600
        
    def connect_serial(self, port, baudrate):
        """连接串口并初始化为接收模式"""
        try:
            if self.serial_port and self.serial_port.is_open:
                self.serial_port.close()

            # 保存连接参数
            self.port_name = port
            self.baudrate = baudrate

            # 初始化为接收模式
            self.set_mode(self.MODE_RECEIVE)

            self.running = True
            self.connection_changed.emit(True)
            return True

        except Exception as e:
            self.error_occurred.emit(f"连接失败: {str(e)}")
            return False
    
    def set_mode(self, mode):
        """设置串口模式（状态机核心）"""
        try:
            # 关闭当前串口
            if self.serial_port and self.serial_port.is_open:
                self.serial_port.close()

            # 根据模式设置串口参数
            if mode == self.MODE_RECEIVE:
                # 接收模式：8位数据，无校验位
                parity = serial.PARITY_NONE
                desc = "接收模式(8位,无校验)"
            elif mode == self.MODE_SEND_ADDR:
                # 地址发送模式：9位数据，MARK校验
                parity = serial.PARITY_MARK
                desc = "地址发送模式(9位,MARK)"
            elif mode == self.MODE_SEND_DATA:
                # 数据发送模式：9位数据，SPACE校验
                parity = serial.PARITY_SPACE
                desc = "数据发送模式(9位,SPACE)"
            else:
                raise ValueError(f"未知模式: {mode}")

            # 创建新的串口连接
            self.serial_port = serial.Serial(
                port=self.port_name,
                baudrate=self.baudrate,
                bytesize=serial.EIGHTBITS,
                parity=parity,
                stopbits=serial.STOPBITS_ONE,
                timeout=0.1
            )

            self.current_mode = mode
            print(f"串口模式切换: {desc}")  # 调试信息
            return True

        except Exception as e:
            self.error_occurred.emit(f"模式切换失败: {str(e)}")
            return False

    def disconnect_serial(self):
        """断开串口"""
        self.running = False
        if self.serial_port and self.serial_port.is_open:
            self.serial_port.close()
        self.connection_changed.emit(False)
    
    def send_address_byte(self, data_byte):
        """发送地址字节（使用MARK模式）"""
        try:
            # 切换到地址发送模式
            if not self.set_mode(self.MODE_SEND_ADDR):
                return False

            # 发送地址字节
            self.serial_port.write(bytes([data_byte]))

            # 立即切换回接收模式
            self.set_mode(self.MODE_RECEIVE)
            return True

        except Exception as e:
            self.error_occurred.emit(f"发送地址字节失败: {str(e)}")
            self.set_mode(self.MODE_RECEIVE)  # 确保恢复接收模式
            return False

    def send_data_bytes(self, data_bytes):
        """发送数据字节（使用SPACE模式）"""
        try:
            if isinstance(data_bytes, int):
                data_bytes = [data_bytes]
            elif isinstance(data_bytes, str):
                data_bytes = list(data_bytes.encode())

            # 切换到数据发送模式
            if not self.set_mode(self.MODE_SEND_DATA):
                return False

            # 连续发送数据字节
            self.serial_port.write(bytes(data_bytes))

            # 立即切换回接收模式
            self.set_mode(self.MODE_RECEIVE)
            return True

        except Exception as e:
            self.error_occurred.emit(f"发送数据字节失败: {str(e)}")
            self.set_mode(self.MODE_RECEIVE)  # 确保恢复接收模式
            return False

    def send_9bit_data(self, data_byte, ninth_bit=1):
        """兼容性函数：发送9位数据"""
        if ninth_bit == 1:
            return self.send_address_byte(data_byte)
        else:
            return self.send_data_bytes([data_byte])
    
    def send_8bit_data(self, data, ninth_bit=0):
        """兼容性函数：发送数据块"""
        if ninth_bit == 1:
            # 如果是地址模式，只发送第一个字节作为地址
            if isinstance(data, (list, tuple)) and len(data) > 0:
                return self.send_address_byte(data[0])
            else:
                return self.send_address_byte(data)
        else:
            # 数据模式，发送所有字节
            return self.send_data_bytes(data)
    
    def add_to_send_queue(self, data, is_9bit=False, ninth_bit=1):
        """添加数据到发送队列"""
        self.send_queue.put((data, is_9bit, ninth_bit))
    
    def run(self):
        """线程主循环"""
        while self.running:
            try:
                # 处理发送队列
                try:
                    data, is_9bit, ninth_bit = self.send_queue.get_nowait()

                    if data == "DELAY_20MS":
                        # 处理20ms延时
                        self.msleep(20)
                        pass
                    elif is_9bit:
                        self.send_9bit_data(data, ninth_bit)
                    else:
                        self.send_8bit_data(data, ninth_bit)
                except queue.Empty:
                    pass

                # 接收数据（确保在接收模式）
                if self.serial_port and self.serial_port.is_open:
                    try:
                        # 确保处于接收模式
                        if self.current_mode != self.MODE_RECEIVE:
                            self.set_mode(self.MODE_RECEIVE)

                        if self.serial_port.in_waiting > 0:
                            data = self.serial_port.read(self.serial_port.in_waiting)
                            if data:  # 确保有数据
                                self.data_received.emit(data, "")
                    except Exception as e:
                        self.error_occurred.emit(f"接收数据错误: {str(e)}")
                        # 尝试恢复接收模式
                        try:
                            self.set_mode(self.MODE_RECEIVE)
                        except:
                            pass

                self.msleep(10)  # 10ms延时

            except Exception as e:
                self.error_occurred.emit(f"线程错误: {str(e)}")
                self.msleep(100)

class NSA5312TestGUI(QMainWindow):
    """NSA5312测试主界面"""
    
    def __init__(self):
        super().__init__()
        self.serial_worker = SerialWorker()
        self.init_ui()
        self.setup_connections()
        self.update_port_list()
        
    def init_ui(self):
        """初始化界面"""
        self.setWindowTitle("NSA5312 UART测试工具 - 状态机模式")
        self.setGeometry(100, 100, 800, 600)
        
        # 创建中央窗口
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 串口配置区域
        config_group = QGroupBox("串口配置")
        config_layout = QGridLayout(config_group)
        
        # 串口选择
        config_layout.addWidget(QLabel("串口:"), 0, 0)
        self.port_combo = QComboBox()
        config_layout.addWidget(self.port_combo, 0, 1)
        
        self.refresh_btn = QPushButton("刷新")
        config_layout.addWidget(self.refresh_btn, 0, 2)
        
        # 波特率
        config_layout.addWidget(QLabel("波特率:"), 1, 0)
        self.baudrate_combo = QComboBox()
        self.baudrate_combo.addItems(['9600', '4800', '19200', '38400', '57600', '115200'])
        self.baudrate_combo.setCurrentText('9600')
        config_layout.addWidget(self.baudrate_combo, 1, 1)
        
        # 连接按钮
        self.connect_btn = QPushButton("连接")
        config_layout.addWidget(self.connect_btn, 1, 2)
        
        main_layout.addWidget(config_group)
        
        # 数据发送区域
        send_group = QGroupBox("数据发送")
        send_layout = QVBoxLayout(send_group)
        
        # 数据包发送 (第9位=1)
        ninbit_packet_layout = QHBoxLayout()
        ninbit_packet_layout.addWidget(QLabel("数据包发送:"))
        self.ninbit_packet_edit = QLineEdit()
        self.ninbit_packet_edit.setPlaceholderText("输入数据包 (如: E1 05 23 00 78) - E1用MARK,其余用SPACE")
        self.ninbit_packet_edit.setText("E1 05 23 00 78")  # 默认值
        ninbit_packet_layout.addWidget(self.ninbit_packet_edit)

        self.send_9bit_packet_btn = QPushButton("发送数据包")
        ninbit_packet_layout.addWidget(self.send_9bit_packet_btn)

        send_layout.addLayout(ninbit_packet_layout)

        # 单字节发送 (第9位=1)
        ninbit_layout = QHBoxLayout()
        ninbit_layout.addWidget(QLabel("单字节发送:"))
        self.ninbit_data_edit = QLineEdit()
        self.ninbit_data_edit.setPlaceholderText("输入单字节 (如: E1) - 自动判断第9位")
        ninbit_layout.addWidget(self.ninbit_data_edit)

        self.send_9bit_btn = QPushButton("发送单字节")
        ninbit_layout.addWidget(self.send_9bit_btn)

        send_layout.addLayout(ninbit_layout)
        
        # 多字节发送 (第9位=1)
        eightbit_layout = QHBoxLayout()
        eightbit_layout.addWidget(QLabel("多字节发送:"))
        self.eightbit_data_edit = QLineEdit()
        self.eightbit_data_edit.setPlaceholderText("输入多字节 (如: E1 04 01 8C) - 自动协议时序")
        eightbit_layout.addWidget(self.eightbit_data_edit)

        self.send_8bit_btn = QPushButton("发送多字节")
        eightbit_layout.addWidget(self.send_8bit_btn)
        
        send_layout.addLayout(eightbit_layout)
        
        # 快捷命令
        cmd_layout = QHBoxLayout()
        cmd_layout.addWidget(QLabel("快捷命令:"))
        
        self.version_cmd_btn = QPushButton("版本查询")
        cmd_layout.addWidget(self.version_cmd_btn)
        
        self.power_off_btn = QPushButton("电源关闭")
        cmd_layout.addWidget(self.power_off_btn)
        
        self.power_on_btn = QPushButton("电源打开")
        cmd_layout.addWidget(self.power_on_btn)
        
        self.owi_switch_btn = QPushButton("OWI切换")
        cmd_layout.addWidget(self.owi_switch_btn)
        
        cmd_layout.addStretch()
        send_layout.addLayout(cmd_layout)
        
        main_layout.addWidget(send_group)
        
        # 数据显示区域
        display_group = QGroupBox("数据监控")
        display_layout = QVBoxLayout(display_group)
        
        # 工具栏
        toolbar_layout = QHBoxLayout()
        self.clear_btn = QPushButton("清空")
        toolbar_layout.addWidget(self.clear_btn)
        
        self.hex_display_cb = QCheckBox("十六进制显示")
        self.hex_display_cb.setChecked(True)
        toolbar_layout.addWidget(self.hex_display_cb)
        
        self.timestamp_cb = QCheckBox("显示时间戳")
        self.timestamp_cb.setChecked(True)
        toolbar_layout.addWidget(self.timestamp_cb)
        
        toolbar_layout.addStretch()
        display_layout.addLayout(toolbar_layout)
        
        # 数据显示文本框
        self.data_display = QTextEdit()
        self.data_display.setFont(QFont("Consolas", 10))
        self.data_display.setReadOnly(True)
        display_layout.addWidget(self.data_display)
        
        main_layout.addWidget(display_group)
        
        # 状态栏
        self.status_bar = self.statusBar()
        self.status_bar.showMessage("未连接")
        
    def setup_connections(self):
        """设置信号连接"""
        # 按钮连接
        self.refresh_btn.clicked.connect(self.update_port_list)
        self.connect_btn.clicked.connect(self.toggle_connection)
        self.send_9bit_packet_btn.clicked.connect(self.send_9bit_packet)
        self.send_9bit_btn.clicked.connect(self.send_9bit_data)
        self.send_8bit_btn.clicked.connect(self.send_8bit_data)
        self.clear_btn.clicked.connect(self.clear_display)
        
        # 快捷命令连接
        self.version_cmd_btn.clicked.connect(self.send_version_query)
        self.power_off_btn.clicked.connect(self.send_power_off)
        self.power_on_btn.clicked.connect(self.send_power_on)
        self.owi_switch_btn.clicked.connect(self.send_owi_switch)
        
        # 串口工作线程连接
        self.serial_worker.data_received.connect(self.on_data_received)
        self.serial_worker.connection_changed.connect(self.on_connection_changed)
        self.serial_worker.error_occurred.connect(self.on_error_occurred)
        
        # 回车键发送
        self.ninbit_packet_edit.returnPressed.connect(self.send_9bit_packet)
        self.ninbit_data_edit.returnPressed.connect(self.send_9bit_data)
        self.eightbit_data_edit.returnPressed.connect(self.send_8bit_data)
        
    def update_port_list(self):
        """更新串口列表"""
        self.port_combo.clear()
        ports = serial.tools.list_ports.comports()
        for port in ports:
            self.port_combo.addItem(f"{port.device} - {port.description}")
        
        if not ports:
            self.port_combo.addItem("未找到串口")
    
    def toggle_connection(self):
        """切换连接状态"""
        if not self.serial_worker.running:
            # 连接
            port_text = self.port_combo.currentText()
            if "未找到串口" in port_text:
                QMessageBox.warning(self, "警告", "请选择有效的串口")
                return
            
            port = port_text.split(" - ")[0]
            baudrate = int(self.baudrate_combo.currentText())
            
            if self.serial_worker.connect_serial(port, baudrate):
                self.serial_worker.start()
        else:
            # 断开
            self.serial_worker.disconnect_serial()
            self.serial_worker.wait()
    
    def calc_crc(self, data):
        """计算CRC-8校验码"""
        crc = 0
        gen_poly = 0x07

        for byte in data:
            crc ^= byte
            for _ in range(8):
                if crc & 0x80:
                    crc = ((crc << 1) ^ gen_poly) & 0xFF
                else:
                    crc = (crc << 1) & 0xFF
        return crc

    def send_9bit_packet(self):
        """发送9位数据包 - 地址字节(MARK)+20ms延时+数据块(SPACE)"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        data_text = self.ninbit_packet_edit.text().strip()
        if not data_text:
            QMessageBox.warning(self, "警告", "请输入要发送的数据包")
            return

        try:
            # 解析十六进制数据
            hex_values = data_text.split()
            if not hex_values:
                QMessageBox.warning(self, "警告", "请输入有效的数据包")
                return

            # 第一个字节作为地址字节，第9位=1 (MARK)
            addr_byte = int(hex_values[0], 16)
            self.serial_worker.add_to_send_queue(addr_byte, True, 1)

            # 添加20ms延时标记
            self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)

            # 后续字节作为数据块，第9位=0 (SPACE)
            if len(hex_values) > 1:
                data_bytes = [int(h, 16) for h in hex_values[1:]]
                self.serial_worker.add_to_send_queue(data_bytes, False, 0)

            # 显示发送的数据
            self.append_to_display(f"TX 数据包: {hex_values[0]}(地址,9位=1) + 20ms + {' '.join(hex_values[1:])}(数据,9位=0)", "blue")

        except ValueError:
            QMessageBox.warning(self, "警告", "请输入有效的十六进制数据")

    def send_9bit_data(self):
        """发送单字节9位数据 - 可选择第9位"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        data_text = self.ninbit_data_edit.text().strip()
        if not data_text:
            QMessageBox.warning(self, "警告", "请输入要发送的数据")
            return

        try:
            # 解析十六进制数据
            data_byte = int(data_text, 16)
            if data_byte > 255:
                QMessageBox.warning(self, "警告", "数据超出8位范围 (0-FF)")
                return

            # 判断是否为地址字节（E1）
            if data_byte == 0xE1:
                ninth_bit = 1  # 地址字节，第9位=1 (MARK)
                desc = "地址,9位=1"
            else:
                ninth_bit = 0  # 数据字节，第9位=0 (SPACE)
                desc = "数据,9位=0"

            self.serial_worker.add_to_send_queue(data_byte, True, ninth_bit)

            # 显示发送的数据
            self.append_to_display(f"TX 单字节: 0x{data_byte:02X} ({desc})", "blue")

        except ValueError:
            QMessageBox.warning(self, "警告", "请输入有效的十六进制数据")

    def send_8bit_data(self):
        """发送多字节数据 - 自动判断第9位"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        data_text = self.eightbit_data_edit.text().strip()
        if not data_text:
            QMessageBox.warning(self, "警告", "请输入要发送的数据")
            return

        try:
            # 解析十六进制数据
            hex_values = data_text.split()
            data = [int(h, 16) for h in hex_values]

            # 判断第一个字节是否为地址
            if data and data[0] == 0xE1:
                # 第一个字节是地址，使用协议时序
                self.serial_worker.add_to_send_queue(data[0], True, 1)  # 地址字节
                self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)  # 20ms延时
                if len(data) > 1:
                    self.serial_worker.add_to_send_queue(data[1:], False, 0)  # 数据字节
                desc = f"{data[0]:02X}(地址) + 20ms + {' '.join([f'{b:02X}' for b in data[1:]])}(数据)"
            else:
                # 全部作为数据字节发送
                self.serial_worker.add_to_send_queue(data, False, 0)
                desc = f"{' '.join([f'{b:02X}' for b in data])}(全部数据,9位=0)"

            # 显示发送的数据
            self.append_to_display(f"TX 多字节: {desc}", "blue")

        except ValueError:
            QMessageBox.warning(self, "警告", "请输入有效的十六进制数据")

    def send_version_query(self):
        """发送版本查询命令 - E1(MARK) + 20ms + 数据块(SPACE)"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        # 先发送地址字节，第9位=1 (MARK)
        self.serial_worker.add_to_send_queue(0xE1, True, 1)

        # 20ms延时
        # self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)

        # 构建数据部分
        cmd_data = [0x04, 0x01]
        crc = self.calc_crc([0xE1] + cmd_data)
        cmd_data.append(crc)

        # 发送数据块，第9位=0 (SPACE)
        self.serial_worker.add_to_send_queue(cmd_data, False, 0)

        hex_str = f"E1(地址,9位=1) + 20ms + {' '.join([f'{b:02X}' for b in cmd_data])}(数据,9位=0)"
        self.append_to_display(f"TX 命令: 版本查询 {hex_str}", "green")

    def send_power_off(self):
        """发送电源关闭命令 - E1(MARK) + 20ms + 数据块(SPACE)"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        # 先发送地址字节，第9位=1 (MARK)
        self.serial_worker.add_to_send_queue(0xE1, True, 1)

        # 20ms延时
        self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)

        # 构建数据部分
        cmd_data = [0x05, 0x20, 0x00]
        crc = self.calc_crc([0xE1] + cmd_data)
        cmd_data.append(crc)

        # 发送数据块，第9位=0 (SPACE)
        self.serial_worker.add_to_send_queue(cmd_data, False, 0)

        hex_str = f"E1(地址,9位=1) + 20ms + {' '.join([f'{b:02X}' for b in cmd_data])}(数据,9位=0)"
        self.append_to_display(f"TX 命令: 电源关闭 {hex_str}", "green")

    def send_power_on(self):
        """发送电源打开命令 - E1(MARK) + 20ms + 数据块(SPACE)"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        # 先发送地址字节，第9位=1 (MARK)
        self.serial_worker.add_to_send_queue(0xE1, True, 1)

        # 20ms延时
        self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)

        # 构建数据部分
        cmd_data = [0x05, 0x20, 0xFF]
        crc = self.calc_crc([0xE1] + cmd_data)
        cmd_data.append(crc)

        # 发送数据块，第9位=0 (SPACE)
        self.serial_worker.add_to_send_queue(cmd_data, False, 0)

        hex_str = f"E1(地址,9位=1) + 20ms + {' '.join([f'{b:02X}' for b in cmd_data])}(数据,9位=0)"
        self.append_to_display(f"TX 命令: 电源打开 {hex_str}", "green")

    def send_owi_switch(self):
        """发送OWI切换命令 - E1(MARK) + 20ms + 数据块(SPACE)"""
        if not self.serial_worker.running:
            QMessageBox.warning(self, "警告", "请先连接串口")
            return

        # 先发送地址字节，第9位=1 (MARK)
        self.serial_worker.add_to_send_queue(0xE1, True, 1)

        # 20ms延时
        self.serial_worker.add_to_send_queue("DELAY_20MS", False, 0)

        # 构建数据部分
        cmd_data = [0x05, 0x22, 0x01]
        crc = self.calc_crc([0xE1] + cmd_data)
        cmd_data.append(crc)

        # 发送数据块，第9位=0 (SPACE)
        self.serial_worker.add_to_send_queue(cmd_data, False, 0)

        hex_str = f"E1(地址,9位=1) + 20ms + {' '.join([f'{b:02X}' for b in cmd_data])}(数据,9位=0)"
        self.append_to_display(f"TX 命令: OWI切换 {hex_str}", "green")

    def append_to_display(self, text, color="black"):
        """添加文本到显示区域"""
        # 使用datetime获取微秒精度的时间戳
        now = datetime.datetime.now()
        timestamp = now.strftime("%H:%M:%S.%f")[:-3]  # 保留3位微秒

        if self.timestamp_cb.isChecked():
            display_text = f"[{timestamp}] {text}"
        else:
            display_text = text

        # 设置颜色
        self.data_display.setTextColor(QColor(color))
        self.data_display.append(display_text)

        # 滚动到底部
        scrollbar = self.data_display.verticalScrollBar()
        scrollbar.setValue(scrollbar.maximum())

    def clear_display(self):
        """清空显示区域"""
        self.data_display.clear()

    def on_data_received(self, data, _):
        """处理接收到的数据"""
        if self.hex_display_cb.isChecked():
            hex_str = ' '.join([f'{b:02X}' for b in data])
            display_text = f"RX: {hex_str}"
        else:
            # ASCII显示
            ascii_str = ''.join([chr(b) if 32 <= b <= 126 else '.' for b in data])
            display_text = f"RX: {ascii_str}"

        self.append_to_display(display_text, "red")

        # 尝试解析NSA5312协议响应
        self.parse_response(data)

    def parse_response(self, data):
        """解析NSA5312协议响应"""
        if len(data) < 4:
            return

        data_list = list(data)

        # 检查是否是有效响应
        if data_list[0] == 0xE1:  # MCU地址
            length = data_list[1]
            if len(data_list) >= length:
                cmd_code = data_list[2]
                status = data_list[3]

                # 验证CRC
                if len(data_list) >= length:
                    calc_crc = self.calc_crc(data_list[:-1])
                    recv_crc = data_list[-1]

                    crc_status = "✓" if calc_crc == recv_crc else "✗"

                    # 解析命令类型
                    cmd_names = {
                        0x01: "版本查询",
                        0x20: "电源控制",
                        0x22: "OWI切换",
                        0x30: "单路ADC",
                        0x40: "64路AD采集",
                        0x41: "获取AD数据"
                    }

                    cmd_name = cmd_names.get(cmd_code, f"未知命令(0x{cmd_code:02X})")

                    if status == 0x00:
                        status_text = "成功"
                        if cmd_code == 0x01 and len(data_list) >= 6:
                            version = data_list[4]
                            status_text += f", 版本: {version}"
                    elif status == 0xF0:
                        status_text = "CRC错误"
                    elif status == 0xF1:
                        status_text = "操作失败"
                    else:
                        status_text = f"状态码: 0x{status:02X}"

                    parse_text = f"解析: {cmd_name} - {status_text} {crc_status}CRC"
                    self.append_to_display(parse_text, "purple")

    def on_connection_changed(self, connected):
        """处理连接状态变化"""
        if connected:
            self.connect_btn.setText("断开")
            self.status_bar.showMessage(f"已连接到 {self.port_combo.currentText().split(' - ')[0]}")

            # 禁用配置控件
            self.port_combo.setEnabled(False)
            self.baudrate_combo.setEnabled(False)
            self.refresh_btn.setEnabled(False)
        else:
            self.connect_btn.setText("连接")
            self.status_bar.showMessage("未连接")

            # 启用配置控件
            self.port_combo.setEnabled(True)
            self.baudrate_combo.setEnabled(True)
            self.refresh_btn.setEnabled(True)

    def on_error_occurred(self, error_msg):
        """处理错误"""
        self.append_to_display(f"错误: {error_msg}", "red")
        QMessageBox.critical(self, "错误", error_msg)

    def closeEvent(self, event):
        """关闭事件"""
        if self.serial_worker.running:
            self.serial_worker.disconnect_serial()
            self.serial_worker.wait()
        event.accept()

def main():
    """主函数"""
    app = QApplication(sys.argv)

    # 设置应用图标和样式
    app.setApplicationName("NSA5312 UART测试工具")
    app.setApplicationVersion("1.0")

    # 创建主窗口
    window = NSA5312TestGUI()
    window.show()

    # 运行应用
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()
